package com.ruoyi.SSL.service.impl;

import java.util.Date;
import java.util.List;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.Method;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ruoyi.SSL.domain.SslDomain;
import com.ruoyi.SSL.domain.SslTrusteeshipService;
import com.ruoyi.SSL.service.ISslDomainService;
import com.ruoyi.SSL.service.ISslTrusteeshipServiceService;
import com.ruoyi.common.config.ServerConfig;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.utils.*;
import com.ruoyi.system.service.ISysConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.SSL.mapper.SslApplyMapper;
import com.ruoyi.SSL.domain.SslApply;
import com.ruoyi.SSL.service.ISslApplyService;
import com.ruoyi.common.core.text.Convert;

/**
 * 证书申请Service业务层处理
 *
 * @author ruoyi
 * @date 2024-09-07
 */
@Service
public class SslApplyServiceImpl implements ISslApplyService
{
    @Autowired
    private SslApplyMapper sslApplyMapper;

    @Autowired
    private ISysConfigService configService;

    @Autowired
    private ISslDomainService domainService;
    @Autowired
    private ISslTrusteeshipServiceService trusteeshipServiceService;


    /**
     * 查询证书申请
     *
     * @param id 证书申请主键
     * @return 证书申请
     */
    @Override
    public SslApply selectSslApplyById(Long id)
    {
        return sslApplyMapper.selectSslApplyById(id);
    }

    /**
     * 查询证书申请列表
     *
     * @param sslApply 证书申请
     * @return 证书申请
     */
    @Override
    public List<SslApply> selectSslApplyList(SslApply sslApply)
    {
        return sslApplyMapper.selectSslApplyList(sslApply);
    }

    /**
     * 新增证书申请
     *
     * @param applyObjJson 证书申请信息对象
     * @return 结果
     */
    @Override
    public AjaxResult insertSslApply(JSONObject applyObjJson)
    {
        String platformDomain = configService.selectConfigByKey("platform.domain");
        //判断当前域名是否已经满足重新续签的条件或者是新的域名
        SslApply sslApply = new SslApply();
        sslApply.setCertificateDomain(applyObjJson.getStr("certificateDomain"));
        sslApply.setStatus("0");
        //判断是否存在待验证记录
        SslDomain sslDomain = new SslDomain();
        List<SslApply> tempList = selectSslApplyList(sslApply);
        if(tempList !=null && tempList.size() > 0){
            sslApply = tempList.get(0);
            sslDomain = domainService.getByDomain(sslApply);
        }else{
            //生成编号
            sslApply.setApplyCode(DateUtil.format(new Date(), "yyyymmddHHMMssSSS")+"_"+RandomUtil.randomString(6));
            sslApply.setPrivateKeyType(applyObjJson.getStr("privateKeyType"));
            sslApply.setIssuingAuthority(applyObjJson.getStr("issuingAuthority"));
            sslApply.setIsUniversal(applyObjJson.getStr("isUniversal"));
            sslDomain = domainService.getByDomain(sslApply);
            sslApply.setMainId(sslDomain.getId());
            sslApply.setCreateTime(DateUtils.getNowDate());
        }
        //创建申请时，自动去把账户注册了 //判断SSL证书厂家
        if(sslApply.getIssuingAuthority().equals("LetsEncryptSSL")) {
            try {
                HttpRequest request = HttpRequest.post(CommUtils.REQ_API_URI+"/SSL/api/v1/ssl_apply");
                applyObjJson.set("applyCode", sslApply.getApplyCode());
                //得到签名
                String sign = SignUtils.createSign(applyObjJson, configService.selectConfigByKey("api.appSecret"));
                //赋值必要请求头的值
                request.header("ssl-sign", sign);
                request.header("Referer", configService.selectConfigByKey("self.domain"));
                request.header("ssl-appid", configService.selectConfigByKey("api.appId"));  //appid
                request.header("ssl-timestamp", String.valueOf(DateUtil.current()));    // 当前时间戳
                //把请求参数赋值到请求中
                request.body(JSONUtil.toJsonStr(applyObjJson));
                //发起请求
                HttpResponse response = request.execute();
                if(response.getStatus() == 200){
                    JSONObject resObj = JSONUtil.parseObj(response.body());
                    if(resObj.getInt("code") == 0){
                        JSONObject dataObj = JSONUtil.parseObj(resObj.getStr("data"));
                        sslApply.setSerRecordCode(dataObj.getStr("applyCode"));
                        if(sslApply.getId() != null){
                            sslApplyMapper.updateSslApply(sslApply);
                        }else{
                            //申请成功！
                            sslApplyMapper.insertSslApply(sslApply);
                        }
                        return AjaxResult.success(resObj.getStr("msg"), sslApply.getId());
                    }else{
                        return AjaxResult.error(resObj.getStr("msg"));
                    }
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }else{
            return AjaxResult.error("厂商开发中！");
        }
        return AjaxResult.error("申请失败！");
    }

    /**
     * 修改证书申请
     *
     * @param sslApply 证书申请
     * @return 结果
     */
    @Override
    public int updateSslApply(SslApply sslApply)
    {
        sslApply.setUpdateTime(DateUtils.getNowDate());
        return sslApplyMapper.updateSslApply(sslApply);
    }

    /**
     * 批量删除证书申请
     *
     * @param ids 需要删除的证书申请主键
     * @return 结果
     */
    @Override
    public int deleteSslApplyByIds(String ids)
    {
        return sslApplyMapper.deleteSslApplyByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除证书申请信息
     *
     * @param id 证书申请主键
     * @return 结果
     */
    @Override
    public int deleteSslApplyById(Long id)
    {
        return sslApplyMapper.deleteSslApplyById(id);
    }

    /**
     * 通过服务器传回来的Id获取验证信息
     * @param sslApply 申请对象
     */
    public AjaxResult getAuthorizationsInfo(SslApply sslApply){
        //创建申请时，自动去把账户注册了 //判断SSL证书厂家
        if(sslApply.getIssuingAuthority().equals("LetsEncryptSSL")) {
            try {
                HttpRequest request = HttpRequest.post(CommUtils.REQ_API_URI+"/SSL/api/v1/get_auth_info");
                //先封装参数得到签名值
                JSONObject paramObj = new JSONObject();
                paramObj.set("serRecordCode", sslApply.getSerRecordCode());
                //得到签名
                String sign = SignUtils.createSign(paramObj, configService.selectConfigByKey("api.appSecret"));
                //赋值必要请求头的值
                request.header("Referer", configService.selectConfigByKey("self.domain"));
                request.header("ssl-sign", sign);   //签名字符串
                request.header("ssl-appid", configService.selectConfigByKey("api.appId"));  //appid
                request.header("ssl-timestamp", String.valueOf(DateUtil.current()));    // 当前时间戳
                //把请求参数赋值到请求中
                request.body(JSONUtil.toJsonStr(paramObj));
                //发起请求
                HttpResponse response = request.execute();
                if(response.getStatus() == 200){
                    JSONObject resObj = JSONUtil.parseObj(response.body());
                    if(resObj.getInt("code") == 0){
                        return AjaxResult.success("获取信息成功！", resObj.get("data"));
                    }else{
                        return AjaxResult.error(resObj.getStr("msg"));
                    }
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return AjaxResult.error("获取错误");
    }

    /**
     * 查询【域名所有权】是否已验证
     * @param sslApply 请求对象
     */
    public AjaxResult authStatus(SslApply sslApply, int idx){
        //创建申请时，自动去把账户注册了 //判断SSL证书厂家
        if(sslApply.getIssuingAuthority().equals("LetsEncryptSSL")) {
            try {
                HttpRequest request = new HttpRequest(CommUtils.REQ_API_URI+"/SSL/api/v1/auth_status");
                request.method(Method.POST);
                //先封装参数得到签名值
                JSONObject paramObj = new JSONObject();
                paramObj.set("serRecordCode", sslApply.getSerRecordCode());
                paramObj.set("idx", idx);
                //得到签名
                String sign = SignUtils.createSign(paramObj, configService.selectConfigByKey("api.appSecret"));
                //赋值必要请求头的值
                request.header("Referer", configService.selectConfigByKey("self.domain"));
                request.header("ssl-sign", sign);   //签名字符串
                request.header("ssl-appid", configService.selectConfigByKey("api.appId"));  //appid
                request.header("ssl-timestamp", String.valueOf(DateUtil.current()));    // 当前时间戳
                //把请求参数赋值到请求中
                request.body(JSONUtil.toJsonStr(paramObj));
                //睡眠30s
                Thread.sleep(30000);
                //发起请求
                HttpResponse response = request.execute();
                if(response.getStatus() == 200){
                    JSONObject resObj = JSONUtil.parseObj(response.body());
                    if(resObj.getInt("code") == 0){
                        return AjaxResult.success("发起验证成功！");
                    }else{
                        return AjaxResult.error(resObj.getStr("msg"));
                    }
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return AjaxResult.error("查询错误");
    }

    public AjaxResult selectAuthStatus(SslDomain sslDomain, int idx){
        //创建申请时，自动去把账户注册了 //判断SSL证书厂家
        if(sslDomain.getIssuingAuthority().equals("LetsEncryptSSL")) {
            try {
                SslApply sslApply = selectSslApplyById(sslDomain.getSslApplyId());
                HttpRequest request = new HttpRequest(CommUtils.REQ_API_URI+"/SSL/api/v1/selectAuthStatus");
                request.method(Method.POST);
                //先封装参数得到签名值
                JSONObject paramObj = new JSONObject();
                paramObj.set("serRecordCode", sslApply.getSerRecordCode());
                paramObj.set("idx", idx);
                //得到签名
                String sign = SignUtils.createSign(paramObj, configService.selectConfigByKey("api.appSecret"));
                //赋值必要请求头的值
                request.header("Referer", configService.selectConfigByKey("self.domain"));
                request.header("ssl-sign", sign);   //签名字符串
                request.header("ssl-appid", configService.selectConfigByKey("api.appId"));  //appid
                request.header("ssl-timestamp", String.valueOf(DateUtil.current()));    // 当前时间戳
                //把请求参数赋值到请求中
                request.body(JSONUtil.toJsonStr(paramObj));
                //发起请求
                HttpResponse response = request.execute();
                if(response.getStatus() == 200){
                    JSONObject resObj = JSONUtil.parseObj(response.body());
                    if(resObj.getInt("code") == 0){
                        return AjaxResult.success("验证成功！");
                    }else{
                        return AjaxResult.error(resObj.getStr("msg"));
                    }
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return AjaxResult.error("下载证书错误！");
    }

    public AjaxResult downCertificate(SslApply sslApply){
        //创建申请时，自动去把账户注册了 //判断SSL证书厂家
        if(sslApply.getIssuingAuthority().equals("LetsEncryptSSL")) {
            try {
                HttpRequest request = new HttpRequest(CommUtils.REQ_API_URI+"/SSL/api/v1/down_certificate");
                request.method(Method.POST);
                //先封装参数得到签名值
                JSONObject paramObj = new JSONObject();
                paramObj.set("serRecordCode", sslApply.getSerRecordCode());
                //得到签名
                String sign = SignUtils.createSign(paramObj, configService.selectConfigByKey("api.appSecret"));
                //赋值必要请求头的值
                request.header("Referer", configService.selectConfigByKey("self.domain"));
                request.header("ssl-sign", sign);   //签名字符串
                request.header("ssl-appid", configService.selectConfigByKey("api.appId"));  //appid
                request.header("ssl-timestamp", String.valueOf(DateUtil.current()));    // 当前时间戳
                //把请求参数赋值到请求中
                request.body(JSONUtil.toJsonStr(paramObj));
                //发起请求
                HttpResponse response = request.execute();
                if(response.getStatus() == 200){
                    JSONObject resObj = JSONUtil.parseObj(response.body());
                    if(resObj.getInt("code") == 0){
                        return AjaxResult.success("验证成功！", resObj.getStr("data"));
                    }else{
                        return AjaxResult.error(resObj.getStr("msg"));
                    }
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return AjaxResult.error("下载证书错误！");
    }

    public AjaxResult getSSLInfo(SslApply sslApply){
        //创建申请时，自动去把账户注册了 //判断SSL证书厂家
        if(sslApply.getIssuingAuthority().equals("LetsEncryptSSL")) {
            try {
                HttpRequest request = new HttpRequest(CommUtils.REQ_API_URI+"/SSL/api/v1/get_ssl_info");
                request.method(Method.POST);
                //先封装参数得到签名值
                JSONObject paramObj = new JSONObject();
                paramObj.set("serRecordCode", sslApply.getSerRecordCode());
                //得到签名
                String sign = SignUtils.createSign(paramObj, configService.selectConfigByKey("api.appSecret"));
                //赋值必要请求头的值
                request.header("Referer", configService.selectConfigByKey("self.domain"));
                request.header("ssl-sign", sign);   //签名字符串
                request.header("ssl-appid", configService.selectConfigByKey("api.appId"));  //appid
                request.header("ssl-timestamp", String.valueOf(DateUtil.current()));    // 当前时间戳
                //把请求参数赋值到请求中
                request.body(JSONUtil.toJsonStr(paramObj));
                //发起请求
                HttpResponse response = request.execute();
                if(response.getStatus() == 200){
                    JSONObject resObj = JSONUtil.parseObj(response.body());
                    if(resObj.getInt("code") == 0){
                        return AjaxResult.success("获取成功！", resObj.getStr("data"));
                    }else{
                        return AjaxResult.error(resObj.getStr("msg"));
                    }
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return AjaxResult.error("获取错误！");
    }

    public AjaxResult synsDomain(SslDomain sslDomain){
        try {
            HttpRequest request = new HttpRequest(CommUtils.REQ_API_URI+"/SSL/api/v1/synsDomain");
            request.method(Method.POST);
            //先封装参数得到签名值
            JSONObject paramObj = JSONUtil.parseObj(sslDomain);
            //得到签名
            String sign = SignUtils.createSign(paramObj, configService.selectConfigByKey("api.appSecret"));
            //赋值必要请求头的值
            request.header("Referer", configService.selectConfigByKey("self.domain"));
            request.header("ssl-sign", sign);   //签名字符串
            request.header("ssl-appid", configService.selectConfigByKey("api.appId"));  //appid
            request.header("ssl-timestamp", String.valueOf(DateUtil.current()));    // 当前时间戳
            //把请求参数赋值到请求中
            request.body(JSONUtil.toJsonStr(paramObj));
            //发起请求
            HttpResponse response = request.execute();
            if(response.getStatus() == 200){
                JSONObject resObj = JSONUtil.parseObj(response.body());
                if(resObj.getInt("code") == 0){
                    return AjaxResult.success("请求成功！", resObj.getStr("data"));
                }else{
                    return AjaxResult.error(resObj.getStr("msg"));
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return AjaxResult.error("请求错误！");
    }

    public AjaxResult getSendEmailInfo(){
        try {
            HttpRequest request = new HttpRequest(CommUtils.REQ_API_URI+"/SSL/api/v1/getSendEmailInfo");
            request.method(Method.POST);
            //先封装参数得到签名值
            JSONObject paramObj = new JSONObject();
            //得到签名
            String sign = SignUtils.createSign(paramObj, configService.selectConfigByKey("api.appSecret"));
            //赋值必要请求头的值
            request.header("Referer", configService.selectConfigByKey("self.domain"));
            request.header("ssl-sign", sign);   //签名字符串
            request.header("ssl-appid", configService.selectConfigByKey("api.appId"));  //appid
            request.header("ssl-timestamp", String.valueOf(DateUtil.current()));    // 当前时间戳
            //把请求参数赋值到请求中
            request.body(JSONUtil.toJsonStr(paramObj));
            //发起请求
            HttpResponse response = request.execute();
            if(response.getStatus() == 200){
                JSONObject resObj = JSONUtil.parseObj(response.body());
                if(resObj.getInt("code") == 0){
                    return AjaxResult.success("请求成功！", resObj.getStr("data"));
                }else{
                    return AjaxResult.error(resObj.getStr("msg"));
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return AjaxResult.error("请求错误！");
    }

    public AjaxResult getDomainRrVal(String domainTxt, String rrVal){
        try {
            HttpRequest request = HttpRequest.get(CommUtils.REQ_API_URI+"/SSL/api/v1/getDomainRrVal");
            //先封装参数得到签名值
            JSONObject paramObj = new JSONObject();
            paramObj.set("domainTxt", domainTxt);
            paramObj.set("rrVal", rrVal);
            //得到签名
            String sign = SignUtils.createSign(paramObj, configService.selectConfigByKey("api.appSecret"));
            //赋值必要请求头的值
            request.header("Referer", configService.selectConfigByKey("self.domain"));
            request.header("ssl-sign", sign);   //签名字符串
            request.header("ssl-appid", configService.selectConfigByKey("api.appId"));  //appid
            request.header("ssl-timestamp", String.valueOf(DateUtil.current()));    // 当前时间戳
            //把请求参数赋值到请求中
            request.body(JSONUtil.toJsonStr(paramObj));
            //发起请求
            HttpResponse response = request.execute();
            if(response.getStatus() == 200){
                JSONObject resObj = JSONUtil.parseObj(response.body());
                if(resObj.getInt("code") == 0){
                    return AjaxResult.success("请求成功！", resObj.getStr("data"));
                }else{
                    return AjaxResult.error(resObj.getStr("msg"));
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return AjaxResult.error("请求错误！");
    }

    /**
     * 获取到服务器特殊域名的字符串
     */
    public AjaxResult isHaveSpecialDomain(String domainTxt){
        try {
            HttpRequest request = new HttpRequest(CommUtils.REQ_API_URI+"/SSL/api/v1/getSpecialDomainSuffix");
            request.method(Method.POST);
            //先封装参数得到签名值
            JSONObject paramObj = new JSONObject();
            //得到签名
            String sign = SignUtils.createSign(paramObj, configService.selectConfigByKey("api.appSecret"));
            //赋值必要请求头的值
            request.header("Referer", configService.selectConfigByKey("self.domain"));
            request.header("ssl-sign", sign);   //签名字符串
            request.header("ssl-appid", configService.selectConfigByKey("api.appId"));  //appid
            request.header("ssl-timestamp", String.valueOf(DateUtil.current()));    // 当前时间戳
            //把请求参数赋值到请求中
            request.body(JSONUtil.toJsonStr(paramObj));
            //发起请求
            HttpResponse response = request.execute();
            if(response.getStatus() == 200){
                JSONObject resObj = JSONUtil.parseObj(response.body());
                if(resObj.getInt("code") == 0){
                    List<SysDictData> dictDataList = JSONUtil.toList(resObj.getStr("data"), SysDictData.class);
                    //判断是否包含了
                    for (SysDictData dictData : dictDataList) {
                        if(domainTxt.contains(dictData.getDictValue())){
                            //获取到根级域名
                            String domainTxt1 = domainTxt.replaceAll(dictData.getDictValue(), "");
                            domainTxt1 = domainTxt1.split("\\.").length>1?domainTxt1.split("\\.")[domainTxt1.split("\\.").length-1]:domainTxt1;
                            return AjaxResult.success("", domainTxt1+dictData.getDictValue());
                        }
                    }
                    return AjaxResult.error("不包含特殊域名！");
                }else{
                    return AjaxResult.error(resObj.getStr("msg"));
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return AjaxResult.error("请求错误！");
    }

    public AjaxResult getNewVersion(){
        try {
            HttpRequest request = new HttpRequest(CommUtils.REQ_API_URI+"/SSL/api/v1/getNewVersion");
            request.method(Method.POST);
            //先封装参数得到签名值
            JSONObject paramObj = new JSONObject();
            //得到签名
            String sign = SignUtils.createSign(paramObj, configService.selectConfigByKey("api.appSecret"));
            //赋值必要请求头的值
            request.header("Referer", configService.selectConfigByKey("self.domain"));
            request.header("ssl-sign", sign);   //签名字符串
            request.header("ssl-appid", configService.selectConfigByKey("api.appId"));  //appid
            request.header("ssl-timestamp", String.valueOf(DateUtil.current()));    // 当前时间戳
            //把请求参数赋值到请求中
            request.body(JSONUtil.toJsonStr(paramObj));
            //发起请求
            HttpResponse response = request.execute();
            if(response.getStatus() == 200){
                JSONObject resObj = JSONUtil.parseObj(response.body());
                if(resObj.getInt("code") == 0){
                    return AjaxResult.success("最新版本：",resObj.getStr("data"));
                }else{
                    return AjaxResult.error(resObj.getStr("msg"));
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return AjaxResult.error("请求错误！");
    }

}
